package com.hdu.dwh.controller;

import com.hdu.dwh.results.PageResponseResult;
import com.hdu.dwh.utils.OperatorUtil;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.annotation.TableName;
import com.hdu.dwh.constants.CommonConstants;
import com.hdu.dwh.dtos.cube_dtos.CubeDto;
import com.hdu.dwh.exception.DataNotFoundException;
import com.hdu.dwh.pojos.Filters;
import com.hdu.dwh.pojos.MetricFilter;
import com.hdu.dwh.pojos.QueryResult;
import com.hdu.dwh.pojos.cube_pojos.Cube;
import com.hdu.dwh.pojos.cube_pojos.Cuboid;
import com.hdu.dwh.pojos.source_access_pojos.DataWarehouseDatabase;
import com.hdu.dwh.results.ResponseResult;
import com.hdu.dwh.service.DataWarehouseDatabaseService;
import com.hdu.dwh.service.cube_service.CubeService;
import com.hdu.dwh.service.cube_service.CuboidService;
import com.hdu.dwh.vos.CubeVo;
import com.hdu.dwh.vos.SimpleCubeVo;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;


@RestController
@RequestMapping("/cube")
@Slf4j
@Tag(name="数据立方体", description = "数据立方体接口")
public class CubeController {
    @Autowired
    private CubeService cubeService;

    @Autowired
    private CuboidService cuboidService;

    @Autowired
    private DataWarehouseDatabaseService dwhDatabaseService;

    @Operation(summary = "创建Cube")
    @PostMapping("/createCube")
    public ResponseResult<CubeVo> createCube(@RequestBody CubeDto cubeDto) {
        Cube cube = new Cube();
        BeanUtils.copyProperties(cubeDto, cube);
        CubeVo cubeVo = cubeService.createCube(cube, cubeDto.getDimensions(), cubeDto.getMetrics(), cubeDto.getFilters());
        cubeVo.setOperator(OperatorUtil.getCurrentOperator());
        return ResponseResult.success(cubeVo);
    }

    @Operation(summary = "查询所有Cube")
    @GetMapping("/getAllCubes/{page}/{pageSize}")
    public ResponseResult<Set<SimpleCubeVo>> getAllCubes(@PathVariable Integer page, @PathVariable Integer pageSize) {
        // 检查分页参数
        if (page == null || page <= 0) {
            page = 1;
        }
        if (pageSize == null || pageSize <= 0) {
            pageSize = 10;
        }

        // 获取所有cube
        Set<SimpleCubeVo> allCubes = cubeService.list().stream().map(cube -> {
            SimpleCubeVo vo = new SimpleCubeVo();
            BeanUtils.copyProperties(cube, vo);
            return vo;
        }).collect(java.util.stream.Collectors.toSet());

        // 实现分页逻辑
        List<SimpleCubeVo> cubeList = new ArrayList<>(allCubes);
        int total = cubeList.size();
        int totalPages = (int) Math.ceil((double) total / pageSize);

        // 计算分页起始和结束索引
        int fromIndex = (page - 1) * pageSize;
        int toIndex = Math.min(fromIndex + pageSize, total);

        // 应用分页
        Set<SimpleCubeVo> pagedCubes = new HashSet<>();
        if (fromIndex < total) {
            pagedCubes = new HashSet<>(cubeList.subList(fromIndex, toIndex));
        }

        return PageResponseResult.success(page, totalPages, pageSize, total, pagedCubes);
    }

    @Operation(summary = "根据id查询Cube")
    @GetMapping("/getCubeDetail/{id}")
    public ResponseResult<CubeVo> getCubeDetail(@PathVariable Integer id) throws Exception {
        Cube cube = cubeService.getById(id);
        if (cube == null) {
            throw new DataNotFoundException(Cube.class.getAnnotation(TableName.class),CommonConstants.RECORD_NOT_EXIST );
        }
        CubeVo cubeVo = this.cubeService.queryCubeDetail(cube);
        return ResponseResult.success(cubeVo);
    }

    @Operation(summary = "根据id删除Cube")
    @DeleteMapping("/deleteCube/{id}")
    public ResponseResult<Void> deleteCube(@PathVariable Integer id) throws DataNotFoundException {
        Cube cube = cubeService.getById(id);
        if (cube == null) {
            throw new DataNotFoundException(Cube.class.getAnnotation(TableName.class),CommonConstants.RECORD_NOT_EXIST );
        }
        this.cubeService.deleteCube(cube);
        return ResponseResult.success();
    }

    @Operation(summary = "构建CuboidSQL")
    @PostMapping("/buildCuboidSQL/{cuboidId}")
    public ResponseResult<String> buildCuboidSQL(@PathVariable Integer cuboidId, @RequestBody Filters filters) throws Exception {
        Cuboid cuboid = this.cuboidService.getById(cuboidId);
        cuboid = this.cubeService.queryCuboidDetail(cuboid);
        String sql = this.cubeService.getCuboidSQL(cuboid, filters.getDimensionFilter(), Set.of(), filters.getPivots(), null, null, "flink");
        // String sql = this.cubeService.getCuboidSQL(cuboid, filters.getDimenisonFilter(), filters.getMetricFilters());
        return ResponseResult.success("生成sql成功", sql);
    }

    @Operation(summary = "查询Cuboid结果")
    @PostMapping("/queryCuboidSQL/{cuboidId}/{page}/{pageSize}")
    public ResponseResult<QueryResult> queryCuboidSQL(@PathVariable Integer cuboidId, @PathVariable Integer page, @PathVariable Integer pageSize, @RequestBody Filters filters) throws Exception {
        Cuboid cuboid = this.cuboidService.getById(cuboidId);
        cuboid = this.cubeService.queryCuboidDetail(cuboid);
        String sql = "";
        if(cuboid.getIsStored() == false) {
            sql = this.cubeService.getCuboidSQL(cuboid, filters.getDimensionFilter(), Set.of(), filters.getPivots() , page, pageSize, "trino");
        } else {
            sql = this.cubeService.getSavedCuboidSQL(cuboid, filters.getDimensionFilter(),filters.getPivots(), page, pageSize, "trino");
        }
        // String sql = this.cubeService.getCuboidSQL(cuboid, filters.getDimenisonFilter(), filters.getMetricFilters());
        QueryResult result = this.cuboidService.executeCuboidSQL(sql);
        return ResponseResult.success("查询成功", result);
    }

    @Operation(summary = "保存Cuboid")
    @PostMapping("/saveCuboid/{cuboidId}")
    public ResponseResult<?> saveCuboid(@PathVariable Integer cuboidId, @RequestParam String saveTableName, @RequestParam String description, @RequestParam Long targetDatabaseId) throws Exception {
        Cuboid cuboid = this.cuboidService.getById(cuboidId);
        DataWarehouseDatabase saveDatabase = this.dwhDatabaseService.getById(targetDatabaseId);
        this.cubeService.saveCuboid(cuboid,saveDatabase, saveTableName, description);
        return ResponseResult.success();
    }

    @Operation(summary = "删除Cuboid")
    @DeleteMapping("/deleteCuboid/{cuboidId}")
    public ResponseResult<?> deleteCuboid(@PathVariable Integer cuboidId) throws DataNotFoundException {
        Cuboid cuboid = this.cuboidService.getById(cuboidId);
        if (cuboid == null) {
            throw new DataNotFoundException(Cuboid.class.getAnnotation(TableName.class),CommonConstants.RECORD_NOT_EXIST );
        }
        this.cubeService.deleteCuboid(cuboid);
        return ResponseResult.success();
    }

}

